package edu.ucsd.ccdb;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;

import edu.ucsd.ccdb.generalDataType.MPIDComparator;
import edu.ucsd.ccdb.generalDataType.MPIDDisplayType;
import edu.ucsd.ccdb.rightClickPopupUtil.RightClickPopupListener;
import edu.ucsd.ccdb.rightClickPopupUtil.RightClickMenu;
import edu.ucsd.ccdb.servlet.ServletSendReceive;
import edu.ucsd.ccdb.tagPopup.util.BareBonesBrowserLauncher;
import edu.ucsd.ccdb.util.RefreshTreeActionListener;
import edu.ucsd.ccdb.util.TreeOperation;
import edu.ucsd.irods.IRODSFileString;
import edu.ucsd.irods.SQLDBQuery;

public class TreePanel extends JPanel implements TreeSelectionListener, ActionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel detailView;
	private JTree tree;
	private JFrame mainFrame;
	
	private JSplitPane bottomPanel; 
	private JSplitPane splitPane ;
	
	private JTextField pathTextField;
	private Integer MPID;
	
	private String username;
	
	private List<String> listFileClicked;
	private JButton refreshTreeButton ;
	
	public TreePanel (String username, Integer initMPID, JFrame frame ) throws Exception {
		super (new GridLayout(1, 0) );
		
		this.mainFrame = frame;
		this.username = username;
	
		listFileClicked = new ArrayList<String>();
		
		Vector<MPIDDisplayType> allMPID = getAllMPID ();
		Collections.sort(allMPID, new MPIDComparator() );	// sort MPID
		
		// fetch the preselected MPID, otherwise get the first MPID
		MPID = getInitialMPID(initMPID, allMPID).getMPID();		
		
		//---------------First split pane: JPanel for MPID and textbox option-----------------
		JPanel infoPane = new JPanel();
		infoPane.setLayout(new BoxLayout(infoPane, BoxLayout.Y_AXIS ));
		
		pathTextField = new JTextField();
		pathTextField.setMaximumSize(new Dimension(400, 20 ) ); 
		pathTextField.setText( SQLDBQuery.getHomeDirectory( MPID, username ) );
		
		//------------------2nd split pane: the tree and detail pane----------------------------------
		// create root node
		String homeDirectory = SQLDBQuery.getHomeDirectory(MPID, username);
		IRODSFileString rootFile = new IRODSFileString(homeDirectory, homeDirectory, true);
		DefaultMutableTreeNode top = new DefaultMutableTreeNode(rootFile);
		
		TreeOperation.createNodes (top);
		
		// create a tree that allows one selection mode
		tree = new JTree(top);
		applyRenderer ( tree );
		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		
		tree.addTreeSelectionListener(this);
		
		JScrollPane treeView = new JScrollPane(tree);

		JPopupMenu popup = new RightClickMenu(tree, frame, rootFile );
		tree.addMouseListener( new RightClickPopupListener(popup, tree) );
		
		detailView = new JPanel();
		
		//-----Populate MPID panel ---------
		JPanel mpidPanel = new JPanel ();		
		JLabel mpidLabel = new JLabel("MPID: " );

		JComboBox comboBox = new JComboBox( allMPID );
		comboBox.setSelectedItem(getInitialMPID(initMPID, allMPID));
		comboBox.addActionListener(this);
		
		refreshTreeButton = new JButton("Refresh");
		refreshTreeButton.addActionListener(new RefreshTreeActionListener(tree, top));
		
		JLabel reportBugLink = new JLabel("<html> <font color=blue><u>Report bugs</u></font></html>");
		reportBugLink.setToolTipText("We'll love you forever for doing this :D " );
		reportBugLink.addMouseListener(new ReportBugMouseListener() );	  
				
		mpidPanel.add(mpidLabel);
		mpidPanel.add(comboBox);
		mpidPanel.add(refreshTreeButton);
		mpidPanel.add(reportBugLink);
		
		//------Populate base folder panel-----------
		JPanel baseFolderPanel = new JPanel ();
		JLabel baseFolderLabel = new JLabel ("Base Folder: ");
		
		baseFolderPanel.add(baseFolderLabel);
		baseFolderPanel.add(pathTextField);
		
		infoPane.add(mpidPanel);
		infoPane.add(Box.createRigidArea( new Dimension (0, 3) ));	// add filler
		infoPane.add( baseFolderPanel );
		infoPane.add(Box.createRigidArea( new Dimension (0, 2) ));	// add filler

		treeView.setMinimumSize(new Dimension ( 400, 200 ));
		detailView.setMinimumSize(new Dimension (400, 200) );
		
		// top Panel contains the infoPane and the treeview
		bottomPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
		bottomPanel.setTopComponent(treeView);
		bottomPanel.setBottomComponent(detailView);
		bottomPanel.setPreferredSize(new Dimension (400, 500) );
		bottomPanel.setDividerLocation(200);	// set divider
		
		// add the scroll to the split pane
		splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT);
		splitPane.setTopComponent(infoPane);
		splitPane.setBottomComponent(bottomPanel);

//		splitPane.setDividerLocation(180);
//		splitPane.setPreferredSize(new Dimension(500, 300));
		
		// put to the main JPanel
		add (splitPane);		
	}
	
	private MPIDDisplayType getInitialMPID ( Integer initMPID, Vector<MPIDDisplayType> allMPID ) {
		
		// special case
		if (initMPID == -1 ) allMPID.get(0).getMPID();
		
		for (MPIDDisplayType element: allMPID) {
			
			if ( initMPID.compareTo(element.getMPID()) == 0 )
				return element;
		}
		
		return allMPID.get(0);
	}
	
	private Vector<MPIDDisplayType> getAllMPID () {
		try {
			return SQLDBQuery.getAllMicroscopy( username );
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return new Vector<MPIDDisplayType>();
	}
	
	private void applyRenderer (JTree tree ) {
		
		tree.setCellRenderer(new MyRenderer());
	}
	
	private ImageIcon createImageIcon (String path) {
		URL imageURL = TreePanel.class.getResource(path);
		
		if (imageURL != null ){
			return new ImageIcon(imageURL);
		}
		System.out.println ("Invalid path");
		return null;
	}
	
	public void valueChanged(TreeSelectionEvent e) {

		DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
		
		if (node == null ) return;
		Object nodeInfo = node.getUserObject();
		
		if (node.isLeaf() ) {
			IRODSFileString file = (IRODSFileString) nodeInfo;
		
			// add subdirectory
			if ( file.isDirectory() ) {

				String query = MainConfiguration.SERVLET_SERVER + MainConfiguration.SERVLET_PARAMETER + file.getAbsolutePath();
				List<IRODSFileString> listFiles = ServletSendReceive.getResponse( query );
				
				if (MainConfiguration.DEBUG ) {
					System.out.println ("Query: " + query);
				}
				
				if (listFiles == null )
					return;
				
				// process		 		
				for (IRODSFileString element: listFiles) {
					
					DefaultMutableTreeNode subNode = new DefaultMutableTreeNode( element );
					node.add(subNode);
				}
			}
		}
		
		// display on the detail Pane
		if ( nodeInfo.getClass().getName().equals( "edu.ucsd.irods.IRODSFileString" ) ) {
			IRODSFileString file = (IRODSFileString) nodeInfo;
			detailView.removeAll();
			detailView.add(new DetailPanel( username, file, mainFrame, MPID, pathTextField.getText(), listFileClicked ));
			
			detailView.validate();
			detailView.repaint();
		}
	}

	/*
	 * (non-Javadoc) This to change the MPID in the drop down , refresh tree and detail Pane
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		System.out.println ("Try to refresh in main panel");
		
		JComboBox cb = (JComboBox) e.getSource();
		MPIDDisplayType selected = (MPIDDisplayType) cb.getSelectedItem();
		MPID = selected.getMPID();
		
		try {
			pathTextField.setText ( SQLDBQuery.getHomeDirectory( selected.getMPID(), username ) );
			
			// refresh treeView 
//			bottomPanel.removeAll();
			bottomPanel.remove(1);	// just remove the thing we need, first split pane.
			
			String homeDirectory = SQLDBQuery.getHomeDirectory( selected.getMPID(), username );
			IRODSFileString rootFile = new IRODSFileString(homeDirectory, homeDirectory, true);
			DefaultMutableTreeNode top = new DefaultMutableTreeNode(rootFile);
			
			TreeOperation.createNodes (top);
			
			tree = new JTree(top);
			applyRenderer ( tree );
			
			// popup here
			JPopupMenu popup = new RightClickMenu(tree, mainFrame, rootFile);
			tree.addMouseListener( new RightClickPopupListener(popup, tree) );
			
			// refresh action listener 
			refreshTreeButton.addActionListener(new RefreshTreeActionListener(tree, top));
			
			tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);			
			tree.addTreeSelectionListener(this);
			
			JScrollPane treeView = new JScrollPane(tree);
//			detailView = new JPanel();
			
			Dimension minimumSize = new Dimension(240, 100);
			detailView.setMinimumSize(minimumSize);
			treeView.setMinimumSize(minimumSize);
			
			bottomPanel.setTopComponent( treeView );			
			bottomPanel.setBottomComponent(detailView);
			bottomPanel.setPreferredSize(new Dimension (400, 500) );
			bottomPanel.setDividerLocation(200);	// set divider

			// NOT SURE NOW, still GUI not showing up
			bottomPanel.revalidate();
			bottomPanel.repaint();
			
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	
	private class MyRenderer extends DefaultTreeCellRenderer {
		
		private static final long serialVersionUID = 1L;
		Icon folderIcon;
		Icon fileIcon;
		
		public MyRenderer () {
			
			this.folderIcon = createImageIcon("/images/smallFolderIcon.jpg");
			this.fileIcon = createImageIcon("/images/smallFileIcon.jpg");
		}
		
		public Component getTreeCellRendererComponent( JTree tree, Object value, boolean sel, 
                				boolean expanded, boolean leaf, int row, boolean hasFocus) {
			
			super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
			
			IRODSFileString file = (IRODSFileString) ((DefaultMutableTreeNode) value).getUserObject();
			
			if ( file.isDirectory() ) {
				setIcon(folderIcon);
			}
			else if (file.isFile() ) {
				setIcon(fileIcon);				
			}
			else setIcon(null);
			
			return this;
		}
	}
	
	private class ReportBugMouseListener implements MouseListener {

		public void mouseClicked(MouseEvent e) {
			BareBonesBrowserLauncher.openURL("http://code.google.com/p/irods-traversal-applet/issues/entry");
		}

		public void mouseEntered(MouseEvent e) {			
		}

		public void mouseExited(MouseEvent e) {			
		}

		public void mousePressed(MouseEvent e) {			
		}

		public void mouseReleased(MouseEvent e) {			
		}
	}
	
	private static void createAndShowGUI ( String username, int MPID) throws Exception {
    	try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} 
    	catch (Exception e) {
			e.printStackTrace();
		}
    	
    	JFrame frame = new JFrame("Data Manager Tool");
    	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	
    	frame.add(new TreePanel( username , MPID, frame ) );
    	
    	frame.pack();
    	frame.setVisible(true);
    }
    
    public static void main (final String [] args )  {
    	javax.swing.SwingUtilities.invokeLater(new Runnable () {

			public void run() {
				try {
					createAndShowGUI( args[0], Integer.parseInt(args[1]) );
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
    	});
    }

}
